package com.wuze.cloud.service.impl;

import com.wuze.cloud.adapter.SysFileAdapter;
import com.wuze.cloud.adapter.SysFolderAdapter;
import com.wuze.cloud.adapter.SysRecyclingAdapter;
import com.wuze.cloud.context.UserContext;
import com.wuze.cloud.dao.*;
import com.wuze.cloud.enums.SysBooleanEnum;
import com.wuze.cloud.exception.SysGlobalException;
import com.wuze.cloud.pojo.*;
import com.wuze.cloud.request.SysRecyclingQuery;
import com.wuze.cloud.request.SysRestoreOrDelQuery;
import com.wuze.cloud.response.SysFileVO;
import com.wuze.cloud.response.SysRecyclingResponse;
import com.wuze.cloud.service.SysRecyclingService;
import com.wuze.cloud.util.UuidUtil;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.assertj.core.util.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.wuze.cloud.enums.SysFileTypeEnum.*;
import static com.wuze.cloud.enums.SysGlobalExceptionEnum.FILE_NOT_FOUND;
import static com.wuze.cloud.enums.SysGlobalExceptionEnum.SPACE_NOT_ENOUGH;
import static com.wuze.cloud.enums.SysStateEnum.*;

/**
 * @Author wuze
 * @Date 2023/5/9 23:03
 * @ClassName: SysRecyclingServiceImpl
 * @Description: TODO
 */
@Service
@Slf4j
public class SysRecyclingServiceImpl implements SysRecyclingService {

    @Autowired
    private SysRecyclingDao recyclingDao;

    @Autowired
    private SysFileDao fileDao;

    @Autowired
    private SysFolderDao folderDao;

    @Autowired
    private SysFileAdapter fileAdapter;

    @Autowired
    private SysFolderAdapter folderAdapter;

    @Autowired
    private SysFolderRelationDao folderRelationDao;

    @Autowired
    private SysStorageDao storageDao;

    @Autowired
    private SysUserDao userDao;

    @Autowired
    private SysRecyclingAdapter recyclingAdapter;

    /**
     * 用户分页查询回收站文件
     * @param query
     * @return
     */
    @Override
    public SysRecyclingResponse findByPage(SysRecyclingQuery query) {

        SysUserDO user = UserContext.getUser();
        SysRecyclingResponse response = new SysRecyclingResponse();

        query.setUserId(user.getId());
        query.setState(RECYCLING.name());
        Integer total = recyclingDao.count(query);
        if(total == 0){
            response.setFiles(Lists.newArrayList());
            response.setFolders(Lists.newArrayList());
            response.setTotal(total);
            return response;
        }
        return recyclingAdapter.buildSysRecyclingResponse(query);
    }


    /**
     * 查询回收站文件夹
     * @param query
     * @return
     */
    @Override
    public List<SysFileVO> findListById(SysRecyclingQuery query) {
        SysUserDO user = UserContext.getUser();

        List<Long> ids = getFolderIdsByFolderIds(Lists.newArrayList(query.getFolderId()));
        List<SysFileDO> files = fileDao.findByFolderIds(ids, user.getId(), RECYCLING.name());
        return fileAdapter.buildSysFileVOS(files);
    }

    /**
     * 获取文件夹及所有子文件夹id
     * @param folderIds
     * @return
     */
    private List<Long> getFolderIdsByFolderIds(List<Long> folderIds){
        List<Long> result = Lists.newArrayList();
        if(CollectionUtils.isEmpty(folderIds)){
            return result;
        }
        result.addAll(folderIds);
        List<SysFolderRelationDO> relationDOS = folderRelationDao.findByPids(folderIds, FOLDER_FILE.name(),RECYCLING.name());
        if(CollectionUtils.isEmpty(relationDOS)){
            return result;
        }
        List<Long> ids = relationDOS.stream().map(SysFolderRelationDO::getChildId).collect(Collectors.toList());
        result.addAll(getFolderIdsByFolderIds(ids));
        return result;
    }

    /**
     * 删除或恢复文件
     * @param query
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void restoreOrDel(SysRestoreOrDelQuery query) {
        if(SysBooleanEnum.TRUE.getCode().equals(query.getIsDel())){
            //执行删除
            delete(query);
        }else {
            //执行恢复
            restore(query);
        }
    }

    /**
     * 执行删除
     * @param query
     */
    private void delete(SysRestoreOrDelQuery query) {
        SysUserDO user = UserContext.getUser();
        query.setUserId(user.getId());
        //删除文件
        Set<Long> ids = getRestoreOrDelFileIds(query);
        log.info("删除文件开始fileIds:{}",query.getFileIds());
        log.info("删除文件夹开始folderIds:{}",query.getFolderIds());
        if(!CollectionUtils.isEmpty(ids)){
            fileDao.batchUpdateFileState(ids,DELETE.name());
            //修改文件夹关系表
            folderRelationDao.batchUpdateState(ids,DELETE.name());
        }
        //恢复文件夹
        if(!CollectionUtils.isEmpty(query.getFolderIds())){
            List<Long> folderIds = getFolderIdsByFolderIds(query.getFolderIds());
            folderDao.batchUpdateFolderState(folderIds, DELETE.name());
            folderRelationDao.batchUpdateState(Sets.newHashSet(folderIds),DELETE.name());
        }
        //修改回收站状态
        if(!CollectionUtils.isEmpty(query.getFileIds())){
            recyclingDao.batchUpdateStateByFileIds(query,DELETE.name());
        }
        if(!CollectionUtils.isEmpty(query.getFolderIds())){
            recyclingDao.batchUpdateStateByFolderIds(query,DELETE.name());
        }

        log.info("删除文件结束ids:{}",ids);
        log.info("删除文件夹结束:{}",query.getFolderIds());

    }
    /**
     * 执行恢复
     * @param query
     */
    private void restore(SysRestoreOrDelQuery query) {
        SysUserDO user = UserContext.getUser();
        query.setUserId(user.getId());
        log.info("恢复文件开始ids{}",query.getFileIds());
        Set<Long> ids = getRestoreOrDelFileIds(query);
        if(!CollectionUtils.isEmpty(ids)){
            List<SysFileDO> files = fileDao.findByIds(ids,RECYCLING.name());
            if(CollectionUtils.isEmpty(files)){
                throw new SysGlobalException(FILE_NOT_FOUND.getCode(),FILE_NOT_FOUND.getMsg());
            }
            //批量恢复
            fileDao.batchUpdateFileState(ids,CREATE.name());
            //修改文件夹关系表状态
            folderRelationDao.batchUpdateState(ids,CREATE.name());
            //修改空间存储表
            SysStorageDO storage = storageDao.findByUserId(user.getId());
            files.forEach(file -> {
                Long size = file.getSize();
                String type = file.getType();
                storage.setCurrSize(storage.getCurrSize() + size);
                if (type.equals(DOCUMENT_FILE.name())) {
                    storage.setDocumentSize(storage.getDocumentSize() + size);
                } else if (type.equals(VIDEO_FILE.name())) {
                    storage.setVideoSize(storage.getVideoSize() + size);
                } else if (type.equals(IMAGE_FILE.name())) {
                    storage.setImageSize(storage.getImageSize() + size);
                } else if (type.equals(OTHER_FILE.name())) {
                    storage.setOrtherSize(storage.getOrtherSize() + size);
                }
            });
            if(storage.getCurrSize()>storage.getMaxSize()){
                throw new SysGlobalException(SPACE_NOT_ENOUGH.getCode(),SPACE_NOT_ENOUGH.getMsg());
            }
            storageDao.update(storage);
        }

        //恢复文件夹
        // 修改父文件夹为根目录且修改文件名
        log.info("恢复文件夹开始ids{}",query.getFolderIds());
        String uuid = UuidUtil.getShortUuid()+"_";
        List<Long> folderIds = getFolderIdsByFolderIds(query.getFolderIds());
        if(!CollectionUtils.isEmpty(folderIds)){
            folderDao.batchUpdateFolderState(folderIds, CREATE.name());
            //恢复文件夹关系表
            Set<Long> set = Sets.newHashSet(folderIds);
            folderRelationDao.batchUpdateState(set, CREATE.name());
            folderDao.batchRestoreOrDel(query.getFolderIds(), user.getRootId(), uuid);
        }
        if(!CollectionUtils.isEmpty(query.getFileIds())){
            //恢复文件夹关系表
            fileDao.batchRestoreOrDel(Sets.newHashSet(query.getFileIds()), user.getRootId(), uuid);
        }

        Set<Long> sets = Sets.newHashSet();
        sets.addAll(query.getFolderIds());
        sets.addAll(query.getFileIds());
        folderRelationDao.batchRestoreOrDel(sets, user.getRootId(), uuid);

        //删除回收站记录
        if(!CollectionUtils.isEmpty(query.getFolderIds())){
            recyclingDao.batchDelByFolderIds(query);
        }
        if(!CollectionUtils.isEmpty(query.getFileIds())){
            recyclingDao.batchDelByFileIds(query);
        }
    }


    /**
     * 构建删除/恢复文件id
     * @param query
     * @return
     */
    private Set<Long> getRestoreOrDelFileIds(SysRestoreOrDelQuery query) {
        SysUserDO user = UserContext.getUser();
        Set<Long> ids = new HashSet<>(query.getFileIds());
        if(!CollectionUtils.isEmpty(query.getFolderIds())){
            List<Long> list = getFolderIdsByFolderIds(query.getFolderIds());
            List<SysFileDO> files = fileDao.findByFolderIds(list , user.getId() , RECYCLING.name());
            ids.addAll(files.stream().map(SysFileDO::getId).collect(Collectors.toSet()));
        }
        return ids;
    }

}
